/*
  版权所有 (c) 2009 Dave Gamble

  特此免费授予任何获得副本的人这个软件和相关文档文件（“软件”）来处理
  软件，不受限制，包括但不限于权利
  使用，复制，修改，合并，发布，分发，再许可和/或销售
  软件的副本，并允许向其提供软件的人
  这样做，但须符合以下条件：

  上述版权声明和本许可声明应包含在
  所有副本或实质性部分软件。

  本软件按“原样”提供，不提供任何形式的明示或暗示的保证，
  包括但不限于适销性、特定用途适用性和非侵权的保证。
  在任何情况下，作者或版权持有人均不对
  任何索赔、损害或其他责任，无论是在合同、侵权或其他方面的行为中，
  由软件或软件的使用或其他交易引起的或与之相关的。
*/

#ifndef cJSON__h
#define cJSON__h

#ifdef __cplusplus
extern "C"
{
#endif
#include <stddef.h>

/* cJSON 类型: */
#define cJSON_False 0
#define cJSON_True 1
#define cJSON_NULL 2
#define cJSON_Number 3
#define cJSON_String 4
#define cJSON_Array 5
#define cJSON_Object 6
	
#define cJSON_IsReference 256
#define cJSON_StringIs 512

/* cJSON 结构: */
typedef struct cJSON {
	struct cJSON *next,*prev;	/* next/prev 允许你在数组/对象链中行走。或者使用 GetArraySize/GetArrayItem/GetObjectItem */
	struct cJSON *child;		/* 数组或对象项将有一个子指针指向数组/对象中的项链。 */

	int type;					/* 项的类型，如上所述。 */

	char *valuestring;			/* 项的字符串，如果 type==cJSON_String */
	int valueint;				/* 项的数字，如果 type==cJSON_Number */
	double valuedouble;			/* 项的数字，如果 type==cJSON_Number */

	char *string;				/* 项的名称字符串，如果此项是对象的子项或子项列表中的项。 */
} cJSON;

typedef struct cJSON_Hooks {
      void *(*malloc_fn)(size_t sz);
      void (*free_fn)(void *ptr);
} cJSON_Hooks;

/* 向 cJSON 提供 malloc, realloc 和 free 函数 */
extern void cJSON_InitHooks(cJSON_Hooks* hooks);


/* 提供一段 JSON，这将返回一个可以查询的 cJSON 对象。完成后调用 cJSON_Delete。 */
extern cJSON *cJSON_Parse( char *value);
/* 将 cJSON 实体渲染为文本以进行传输/存储。完成后释放 char*。 */
extern char  *cJSON_Print(cJSON *item);
/* 将 cJSON 实体渲染为文本以进行传输/存储，没有任何格式。完成后释放 char*。 */
extern char  *cJSON_PrintUnformatted(cJSON *item);
/* 使用缓冲策略将 cJSON 实体渲染为文本。prebuffer 是对最终大小的猜测。猜得好可以减少重新分配。fmt=0 给出无格式，=1 给出格式化 */
extern char *cJSON_PrintBuffered(cJSON *item,int prebuffer,int fmt);
/* 删除一个 cJSON 实体及其所有子实体。 */
extern void   cJSON_Delete(cJSON *c);

/* 返回数组（或对象）中的项数。 */
extern int	  cJSON_GetArraySize(cJSON *array);
/* 从数组 "array" 中检索第 "item" 项。如果失败返回 NULL。 */
extern cJSON *cJSON_GetArrayItem(cJSON *array,int item);
/* 从对象中获取项 "string"。不区分大小写。 */
extern cJSON *cJSON_GetObjectItem(cJSON *object, char *string);

/* 用于分析失败的解析。这将返回指向解析错误的指针。你可能需要向后看几个字符才能理解它。当 cJSON_Parse() 返回 0 时定义。当 cJSON_Parse() 成功时为 0。 */
extern  char *cJSON_GetErrorPtr(void);
	
/* 这些调用创建适当类型的 cJSON 项。 */
extern cJSON *cJSON_CreateNull(void);
extern cJSON *cJSON_CreateTrue(void);
extern cJSON *cJSON_CreateFalse(void);
extern cJSON *cJSON_CreateBool(int b);
extern cJSON *cJSON_CreateNumber(double num);
extern cJSON *cJSON_CreateString( char *string);
extern cJSON *cJSON_CreateArray(void);
extern cJSON *cJSON_CreateObject(void);

/* 这些实用程序创建一个包含 count 项的数组。 */
extern cJSON *cJSON_CreateIntArray( int *numbers,int count);
extern cJSON *cJSON_CreateFloatArray( float *numbers,int count);
extern cJSON *cJSON_CreateDoubleArray( double *numbers,int count);
extern cJSON *cJSON_CreateStringArray( char **strings,int count);

/* 将项追加到指定的数组/对象。 */
extern void cJSON_AddItemToArray(cJSON *array, cJSON *item);
extern void	cJSON_AddItemToObject(cJSON *object, char *string,cJSON *item);
extern void	cJSON_AddItemToObjectCS(cJSON *object, char *string,cJSON *item);	/* 当字符串绝对是常量（例如字面量，或几乎不变），并且绝对会存活于 cJSON 对象时使用此函数 */
/* 将项的引用追加到指定的数组/对象。当你想将现有的 cJSON 添加到新的 cJSON，但不想破坏现有的 cJSON 时使用此函数。 */
extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
extern void	cJSON_AddItemReferenceToObject(cJSON *object, char *string,cJSON *item);

/* 从数组/对象中移除/分离项。 */
extern cJSON *cJSON_DetachItemFromArray(cJSON *array,int which);
extern void   cJSON_DeleteItemFromArray(cJSON *array,int which);
extern cJSON *cJSON_DetachItemFromObject(cJSON *object, char *string);
extern void   cJSON_DeleteItemFromObject(cJSON *object, char *string);
	
/* 更新数组项。 */
extern void cJSON_InsertItemInArray(cJSON *array,int which,cJSON *newitem);	/* 将现有项向右移动。 */
extern void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem);
extern void cJSON_ReplaceItemInObject(cJSON *object, char *string,cJSON *newitem);

/* 复制一个 cJSON 项 */
extern cJSON *cJSON_Duplicate(cJSON *item,int recurse);
/* Duplicate 将创建一个新的、相同的 cJSON 项，你传递的项将在新的内存中，
需要被释放。当 recurse!=0 时，它将复制任何连接到该项的子项。
从 Duplicate 返回时，item->next 和 ->prev 指针始终为零。 */

/* ParseWithOpts 允许你要求（并检查）JSON 是空终止的，并检索解析的最终字节的指针。 */
extern cJSON *cJSON_ParseWithOpts( char *value, char **return_parse_end,int require_null_terminated);

extern void cJSON_Minify(char *json);

/* 快速创建事物的宏。 */
#define cJSON_AddNullToObject(object,name)		cJSON_AddItemToObject(object, name, cJSON_CreateNull())
#define cJSON_AddTrueToObject(object,name)		cJSON_AddItemToObject(object, name, cJSON_CreateTrue())
#define cJSON_AddFalseToObject(object,name)		cJSON_AddItemToObject(object, name, cJSON_CreateFalse())
#define cJSON_AddBoolToObject(object,name,b)	cJSON_AddItemToObject(object, name, cJSON_CreateBool(b))
#define cJSON_AddNumberToObject(object,name,n)	cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n))
#define cJSON_AddStringToObject(object,name,s)	cJSON_AddItemToObject(object, name, cJSON_CreateString(s))

/* 当分配一个整数值时，需要将其传播到 valuedouble 中。 */
#define cJSON_SetIntValue(object,val)			((object)?(object)->valueint=(object)->valuedouble=(val):(val))
#define cJSON_SetNumberValue(object,val)		((object)?(object)->valueint=(object)->valuedouble=(val):(val))

#ifdef __cplusplus
}
#endif

#endif
